using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Ajax;
using Sedodream.Sudoku.Board;
using Sudoku.Web.MVC.Models;
using Sedodream.Sudoku.Players;
using System.Text;

namespace Sudoku.Web.MVC.Controllers
{
    public class SudokuController : Controller
    {
        private const int MaxNumMoves = 10000;
        private readonly IDictionary<int, IBoard> mBoardMap;


        public SudokuController()
            : base()
        {
            mBoardMap = new Dictionary<int, IBoard>();
            string easyStr =
@"900 005 681
060 280 700
000 006 905
080 002 046
005 000 300
190 500 070
802 900 000
009 027 060
674 800 003";
            mBoardMap.Add(1, BoardFactory.CreateBoard(easyStr));

            string mediumStr =
@"000 072 160
407 000 095
009 060 038
050 001 002
801 706 903
300 800 040
630 080 500
120 000 407
098 240 000";
            mBoardMap.Add(2, BoardFactory.CreateBoard(mediumStr));

            string hardSr =
@"300 000 008
076 100 020
000 020 050

000 004 680
000 000 000
021 300 000

090 040 000
060 009 730
400 000 009";
            mBoardMap.Add(3, BoardFactory.CreateBoard(hardSr));
        }


        //
        // GET: /Sudoku/
        
        public ActionResult Index()
        {
            return View(new BoardModel());
        }

        // GET: /Sudoku/ClearBoard
        public ActionResult ClearBoard()
        {
            return RedirectToAction("Index");
        }

        public ActionResult PrefillBoard(int? id)
        {
            if (!id.HasValue)
            {
                string message = string.Format("id must have a value, but it was null");
                throw new ArgumentNullException(message);
            }

            IBoard board = mBoardMap[id.Value];
            if (board == null)
            {
                string message = string.Format("No board found with id [{0}]",id);
                throw new ArgumentException(message);
            }

            BoardModel model = new BoardModel { StartBoard = board };

            return View("Index", model);
            //RedirectToAction puts the value of the model object into the URL
            //return RedirectToAction("Index", model);
        }





        // POST: /Sudoku/Solve
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Solve(IBoard board)
        {
            if (board == null) { throw new ArgumentNullException("board"); }

            //First clone the board becuase when being solved it will be modified
            int?[,] startBoardData = new int?[board.BoardData.SideLength, board.BoardData.SideLength];
            for (int row = 0; row < board.BoardData.SideLength; row++)
            {
                for (int col = 0; col < board.BoardData.SideLength; col++)
                {
                    startBoardData[row, col] = board.BoardData[row, col];
                }
            }
            IBoard startBoard = BoardFactory.CreateBoard(new BoardData(board.BoardData.Size, startBoardData));



            IPlayer player = new SimplePlayer();
            player.MaxNumMoves = MaxNumMoves;

            DateTime start = DateTime.Now;

            IBoard resultBoard = player.StartPlay(board);

            DateTime end = DateTime.Now;

            if (resultBoard != null)
            {
                //TODO: Put more info here
                TimeSpan timeSpent = end.Subtract(start);

                StringBuilder sb = new StringBuilder();
                sb.Append("Board solved: ");
                string newLine = Environment.NewLine;
                sb.Append(string.Format("Num moves played: {0}{1}", player.NumMovesPlayed, newLine));
                sb.Append(string.Format(@"Time spent: {0}{1}", timeSpent, newLine));

                ViewData["ResultMessage"] = sb.ToString();
            }
            else
            {
                ViewData["ResultMessage"] = "Unable to find a solution";
            }

            string test = "dkdldldldld";
            
            //send the board to be solved

            return View("Index", new BoardModel { StartBoard = startBoard, EndBoard = resultBoard });
        }

        // POST: /Sudoku/QuickUpdate
        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult QuickUpdate(string startBoardString)
        {
            if (startBoardString == null) { throw new ArgumentNullException("startBoardString"); }
            
            try
            {
                IBoard board = BoardFactory.CreateBoard(startBoardString);

                return View("Index", new BoardModel { StartBoard = board });
            }
            catch (Exception ex)    //TODO: Narrow down this catch statement
            {
                ViewData["ResultMessage"] = "An error has occurred";
                return View("Index", new BoardModel());
            }
        }
        public ActionResult ValidateQuickUpdateString(string startBoardString)
        {
            //TODO: Implement this

            throw new NotImplementedException();
        }


    }
}
